<?php

namespace ServiceCenter;

/**
 * Created by PhpStorm.
 * User: 554665488
 * Date: 2018-6-27
 * Time: 20:46
 * @description:服务中心
 * @Author: yfl
 * @QQ 554665488
 */
use Swoole\Http\Request;
use Swoole\Http\Response;

include dirname(__DIR__) . '/autoLoader.php';

class Rpc
{
    protected $serverCenter;

    protected $redis;

    protected $clientService;

    public function __construct($config)
    {
        $serverCenter = new \Swoole\Websocket\Server('0.0.0.0', 9501);
        $this->serverCenter = $serverCenter;
        $this->serverCenter->set($config);
        $this->serverCenter->on('workerStart', [$this, 'onWorkerStart']);
        $this->serverCenter->on('message', [$this, 'onMessage']);
        $this->serverCenter->on('request', [$this, 'onRequest']);
        $this->serverCenter->on('close', [$this, 'onClose']);

        //监听TCP客户端  多端口
        $this->clientService = $this->serverCenter->addlistener('0.0.0.0', 9503, SWOOLE_SOCK_TCP);
        //设置客户端监听
        $this->clientService->set([
            'worker_num' => 6,
//            'package_max_length' => 1024 * 1024 * 10,
            'max_request' => 3000,
        ]);
        $this->clientService->on('receive', [$this, 'onReceive']);
        $this->clientService->on('close', [$this, 'onTcpClose']);
        $this->serverCenter->start();
    }

    public function onWorkerStart($server, $worker_id)
    {

//        if ($worker_id == 0) {
        //服务启动注册自动加载

//        }
        $this->redis = new \Redis();
        $this->redis->connect('127.0.0.1', 6379);
        $this->redis->auth('redis123456');
//        var_dump($this->redis);
    }

    public function onMessage($server, $frame)
    {
        $data = json_decode($frame->data, true);
        $fd = $frame->fd;
        $stats_key = $data['ip'] . '-' . json_encode($data['port']);
        if (isset($data['method']) && $data['method'] == 'register') {
            $service_key = 'service:' . $data['serverName'];

            $redisValue = json_encode([
                'ip' => $data['ip'],
                'port' => $data['port']
            ]);
//            var_dump('服务的key', $service_key);
            $res = $this->redis->sAdd($service_key, $redisValue);
            $redis = $this->redis;
            if ($res) {
                $server->tick(3000, function ($id) use ($server, $fd, $redis, $service_key, $redisValue, $stats_key) {
                    //不存活的链接
                    if (!$server->exist($fd)) {
                        //检测服务是否存在redis
                        if ($redis->sIsMember($service_key, $redisValue)) {
                            //存在则移除 只是移除 如果需要更新状态
                            $redis->sRem($service_key, $redisValue);
//                            var_dump('删除key',$stats_key);
                            $redis->del($stats_key);
                        }
//                        var_dump('redis集合', $redis->sMembers($service_key));
                        $server->clearTimer($id);
                    }
                });
            }
        } elseif (isset($data['method']) && $data['method'] == 'status') {
//            var_dump('状态key', $stats_key);
            $data = [
                'load' => $data['load'],
                'connection_num' => $data['connection_num'],
                'tasking_num' => $data['tasking_num']
            ];
            $this->redis->set($stats_key, json_encode($data));
        } else {
            $server->push($frame->fd, '非法请求');
        }
//        var_dump('维持心跳');
    }

    //Tcp 链接事件
    public function onReceive($server, $fd, $reactor_id, $data)
    {
        $serviceInfo = json_decode($data, true);
//        var_dump($serviceInfo);
        $status = [];
        $it = null;
        //遍历某个集合
        while (($arr_mems = $this->redis->sScan('service:' . $serviceInfo['service'], $it)) !== false) {

            if (count($arr_mems) > 0) {
                foreach ($arr_mems as $str_mem) {
                    $serverRedis = json_decode($str_mem, true);
//                    var_dump($serverRedis);
                    //获取到单台服务器的状态
                    $status_key = $serverRedis['ip'] . '-' . json_encode($serverRedis['port']);
                    $status[$status_key] = array_values(json_decode($this->redis->get($status_key), true));
//                    $status[$status_key]=json_decode($this->redis->get($status_key),true);

                }
            }

        }

        $options = [
            'load' => [  //系统负载
                '0-1' => 20,
                '1-2' => 10,
                '2-' => 0
            ],
            'connection_num' => [  //连接数
                '0-100' => 20,
                '100-200' => 10,
                '200-300' => 5,
                '300-' => 0
            ],
            'tasking' => [    //任务排队数
                '0-10' => 10,
                '10-20' => 5,
                '20-' => 0
            ]
        ];
        $grade = new \Grades();
        $getService = $grade->execute($status, $options);
//        var_dump($getService);
//        var_dump($status);
//        var_dump($serviceInfo);
//        $goodsService = "distributed\\" . $serviceInfo['service'];
//        $action = $serviceInfo['action'];
//        $goodsServiceObj = new $goodsService();
//        var_dump($goodsServiceObj);
//        $response = $goodsServiceObj->$action();

        $server->send($fd, $getService);
    }

    //响应HTTP请求
    public function onRequest(Request $request, Response $response)
    {
//        echo 'http请求触发';
        $serviceInfo = $request->post;
//        var_dump($serviceInfo);
        $goodsService = "distributed\\" . $serviceInfo['service'];
        $action = $serviceInfo['action'];
        $goodsServiceObj = new $goodsService();
//        var_dump($goodsServiceObj);
        $responseInfo = $goodsServiceObj->$action();
//        var_dump($responseInfo);
//        var_dump($this->serverCenter->connection_list(0,10));
//        foreach ($this->clientService->connections as $index => $fd) {
//             $this->clientService->push($fd,$responseInfo);
//        }
        $response->header('Content-Type', 'text/html');
        $response->header('Charset', 'utf-8');
        $response->header('Content-Length', strlen($responseInfo));
        $response->cookie('key', 'value');
        $response->write($responseInfo);
//        $response->cookie('key','value');
//        $response->status(200);
//        $response->gzip(1);
//        $response->end("<meta charset='UTF-8' />".$responseInfo);
    }

    public function onTcpClose($server, $fd)
    {
        var_dump('tcp关闭了', $fd);
    }

    public function onClose($server, $fd)
    {
        var_dump('关闭了', $fd);
    }
}

$config = [
    'worker_num' => 6,
    'package_max_length' => 1024 * 1024 * 10,
    'max_request' => 3000,
    'heartbeat_idle_time' => 5,//连接最大的空闲时间
    'heartbeat_check_interval' => 4 //定时检测在线列表
];

new Rpc($config);